import useCLodop from '@/store/cLodop'
import {downLacolFile} from '@/util/common'
import {ClassType} from '@/api/config'
import {strNumReader} from '@/util/math'
const cLodopStore = useCLodop.setup().store
/** 打印控件部分 */
//状态
export enum CLodopStatus{
  NotReady, Loading, Ready, NeedInstall, NeedUpgrade
}
//检查当前浏览器是否需要安装CLodop插件(CLodop官方的方法)
export const needCLodop = () => {
  return true
}

//条形码类型 其中QRCode和PDF417是二维码，其它为一维码
type BarcodeType='128A'|'128B'|'128C'|'128Auto'|'EAN8'|'EAN13'|'EAN128A'|'EAN128B'|'EAN128C'|'Code39'|'39Extended'|'2_5interleaved'|'2_5industrial'|'2_5matrix'|'UPC_A'|'UPC_E0'|'UPC_E1'|'UPCsupp2'|'UPCsupp5'|'Code93'|'93Extended'|'MSI'|'PostNet'|'Codabar'|'QRCode'|'PDF417'

const DefualtBarcodeType:BarcodeType = '128Auto'
//Clodop接口 具体参数意义看Lodop技术手册和云打印C-lodop技术手册
type LodopInt=number|string
//按位类型 bit 0,1,2,3,4,5,
type LodopBit=number
export interface Clodop{
  CVERSION:string //版本号
  NEWPAGE() //强制分页
  PRINT_INIT(strTaskName?:string):boolean //打印初始化
  PRINT():boolean //打印 正确打印时返回真，打印出错时返回假
  PREVIEW(oView?:string, iW?:number, iH?:number, iOption?:LodopBit) //打印预览
  GET_PRINTER_COUNT():number //获取打印机个数
  GET_PRINTER_NAME(strPrinterIDandType:LodopInt):string //获得打印设备名称 返回字符型结果，代表对应的名称或属性值，如返回空表示失败或无该设备
  SET_LICENSES(strCompanyName:string, strLicense:string, strLicenseA?:string, strLicenseB?:string) //设置公司信息
  SET_PRINT_PAGESIZE(intOrient:number, PageWidth:LodopInt, PageHeight:LodopInt, strPageName:string) //设定纸张大小
  SET_PRINT_MODE(mode:string, value:boolean|number) //设置打印模式
  SET_PRINT_STYLE(strStyleName:LodopInt, varStyleValue:LodopInt) //打印风格设置
  //数字型时，表示是序号，以其增加的先后自然顺序为准，从1开始，所有打印对象都参与排序，包括超文本、纯文本、图片、图线、图表、条码等。  如果序号为0，代表当前（最后加入的那个）数据项；如果序号是负数，代表前面加入的数据项，该值为前移个数偏移量。
  SET_PRINT_STYLEA(varItemNameID:LodopInt, strStyleName:LodopInt, varStyleValue:LodopInt) //增强型 设置打印项风格A
  SET_PRINTER_INDEX(driver:string|null, PrinterIDandName?:string) //指定打印机
  ADD_PRINT_HTM(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, strHtmlContent:string) //HTML打印预览
  ADD_PRINT_BARCODE(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, CodeType:BarcodeType, CodeValue:LodopInt) //增加条形码
  ADD_PRINT_TEXT(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, strContent:string) //增加纯文本打印项
  ADD_PRINT_PDF(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, strContent:string) //PDF文档格式打印项
  ADD_PRINT_IMAGE(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, strContent:string) //增加图片打印项
  ADD_PRINT_TABLE(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, strHtm:string) //增加表格打印项
  ADD_PRINT_LINE(Top1:LodopInt, Left1:LodopInt, Top2:LodopInt, Left2:LodopInt, intLineStyle:number, intLineWidth:number) //增加直线
  ADD_PRINT_RECT(Top:LodopInt, Left:LodopInt, Width:LodopInt, Height:LodopInt, intLineStyle:number, intLineWidth:number) //增加矩形框
}

//定义一个空的 以便在CLodop没加载好时也可调用这个函数
export let getCLodop = ():null|Clodop => {
  return null
}

//加载'|'初次进入或者更改端口号后
export const loadCLodop = () => {
  if (needCLodop()) {
    cLodopStore.setLodopStatus(CLodopStatus.Loading)
    // store.commit('cLodop/setLodopStatus', CLodopStatus.Loading)
    const baseUrl = import.meta.env.VITE_APP_BASE_CLODOP_URL
    const ports:Array<number> = cLodopStore.getLodopPorts
    const head =
      document.head ||
      document.getElementsByTagName('head')[0] ||
      document.documentElement
    let loadErrNum = 0
    const len = ports.length
    const onError = () => {
      if (++loadErrNum === len) {
        // store.commit('cLodop/setLodopStatus', CLodopStatus.NeedInstall)
        cLodopStore.setLodopStatus(CLodopStatus.NeedInstall)
      }
    }
    for (let i = 0, l = len; i < l; i++) {
      const script = document.createElement('script')
      script.src = baseUrl + ':' + ports[i] + '/' + 'CLodopfuncs.js?priority=' + (l - i)
      script.type = 'text\/javascript'
      //加载错误计数
      script.onerror = onError
      //加载完成
      script.onload = (evt) => {
        //已经加载则不处理 避免一些潜在问题
        const status:CLodopStatus = cLodopStore.getLodopStatus
        if (status === CLodopStatus.Ready) return
        //没有挂载getCLodop'|'则说明是错误的端口
        if (!window['getCLodop']) {
          onError()
          return
        }
        getCLodop = window['getCLodop']
        const clodop = getCLodop()
        if (clodop) {
          clodop.SET_LICENSES(
            '道可名康医学发展（上海）有限公司',
            '50DF008575B58E4C92D4CA39F040596B98E',
            '道可名康醫學發展（上海）有限公司',
            'E4DEE5B448EFB51C4C364D4A15602C703D8'
          )
          clodop.SET_LICENSES(
            'THIRD LICENSE',
            '',
            'Daoke Mingkang medical development (Shanghai) Co., Ltd',
            '809BA7B012266CE8EA02D81154484E5C6F7'
          )
        }
        //版本过低 4.1.5.9
        if (clodop && clodop.CVERSION < '4.1.5.9') {
          console.log('clodop.CVERSION', clodop.CVERSION)
          // store.commit('cLodop/setLodopStatus', CLodopStatus.NeedUpgrade)
          cLodopStore.setLodopStatus(CLodopStatus.NeedUpgrade)
        } else {
          // store.commit('cLodop/setLodopStatus', CLodopStatus.Ready)
          cLodopStore.setLodopStatus(CLodopStatus.Ready)
        }
      }
      head.insertBefore(script, head.firstChild)
    }
  }
}

//设置注册信息
export const resetLicenses = (clodop:Clodop) => {
  clodop.SET_LICENSES(
    '道可名康医学发展（上海）有限公司',
    '50DF008575B58E4C92D4CA39F040596B98E',
    '道可名康醫學發展（上海）有限公司',
    'E4DEE5B448EFB51C4C364D4A15602C703D8'
  )
  clodop.SET_LICENSES(
    'THIRD LICENSE',
    '',
    'Daoke Mingkang medical development (Shanghai) Co., Ltd',
    '809BA7B012266CE8EA02D81154484E5C6F7'
  )
}

import {ElMessage, ElMessageBox} from 'element-plus'


//下载消息
export const showCLodopDownMeaasage = (message:string, title:string) => {
  ElMessageBox.confirm(message, title, {
    cancelButtonText:'取消',
    confirmButtonText:'确认',
    type:'warning'
  }).then(() => {
    //版本过低
    downLacolFile('CLopdop.rar', '/resources/CLodop.rar')
  }).catch(() => {
    //
  })
}

//如果没有准备好,显示提示
export const showCLodopTips = ():boolean => {
  const status:CLodopStatus = cLodopStore.getLodopStatus
  const clodop = getCLodop()
  if (status === CLodopStatus.NeedUpgrade && clodop) {
    showCLodopDownMeaasage('打印控件需要升级，点击下载安装完成升级，刷新页面', '升级')
    return false
  }
  //未下载完毕
  else if (status === CLodopStatus.Loading) {
    ElMessage.warning('打印控件载入中...')
    return false
  }
  //端口没找到或者是错误的端口
  else if (status === CLodopStatus.NeedInstall) {
    const ports:Array<number> = cLodopStore.getLodopPorts
    const portsStr = ports.join(',')
    showCLodopDownMeaasage('打印控件加载出错,请下载并安装打印控件;安装完成后请刷新页面;如已安装，请查看端口' + portsStr + ' 是否配置正确', '安装')
    return false
  }
  //还未执行加载代码
  else if (status === CLodopStatus.NotReady) {
    ElMessage.warning('暂未开始加载打印控件')
    loadCLodop()
    return false
  }
  else if (status === CLodopStatus.Ready) {
    return true
  } else {
    return false
  }
}

//打印类型 条码或报告
export type PrintType='barcode'|'report'|'pdf'
/**打印机设置部分*/
//获取打印机列表
export const getPrintList = ():Array<string> => {
  if (!showCLodopTips()) return []
  const clodop = getCLodop()
  const printNameList:Array<string> = []
  if (clodop) {
    const printNum = clodop.GET_PRINTER_COUNT() //打印机总数
    for (let i = 0; i < printNum; i++) {
      printNameList.push(clodop.GET_PRINTER_NAME(i))
    }
    const newArr = Array.from(new Set(printNameList))
    if (newArr.length !== printNameList.length) {
      ElMessage.warning('计算机中存在重复名称的打印机，请先重命名重复打印机的名称')
      return []
    } else {
      return printNameList
    }
  }
  return printNameList
}

//获取名称
export const getPrintTypeName = (printType:PrintType) => {
  if (printType === 'barcode') {
    return '条码打印机'
  } else if (printType === 'report') {
    return '报告打印机'
  } else if (printType === 'pdf') {
    return 'PDF打印机'
  } else {
    return ''
  }
}

//获取打印机
const getPrintName = (printType:PrintType) => {
  if (printType === 'barcode') {
    return cLodopStore.getBarcodePrint
  } else if (printType === 'report') {
    return cLodopStore.getReprotPrint
  } else if (printType === 'pdf') {
    return cLodopStore.getPdfPrint
  } else {
    return ''
  }
}

//检验打印机设置
export const checkPrint = (printType:PrintType, showPrint = true):boolean => {
  const print = getPrintName(printType)
  const printName = getPrintTypeName(printType)
  if (!print) {
    if (showPrint) {
      // store.commit('cLodop/setShowPrinter', true)
      cLodopStore.setShowPrinter(true)
    }
    ElMessage.warning('请选择' + printName)
    return false
  }
  const arr = getPrintList()
  if (arr.indexOf(print) === -1) {
    if (showPrint) {
      // store.commit('cLodop/setShowPrinter', true)
      cLodopStore.setShowPrinter(true)
    }
    ElMessage.warning(printName + '已被移除,请重新选择')
    return false
  } else {
    return true
  }
}

/**检查打印机设置*/

/** 打印预览部分 */
import {Dictionary} from '@/api/config'

//打印模式，打印还是预览
export type PrintMode='print'|'preview'

//打印风格类型
export type StyleName='FontName'|'FontSize'|'FontColor'|'Bold'|'Italic'|'Underline'|'Alignment'|'Angle'|'ItemType'|'HOrient'|'VOrient'|'PenWidth'|'PenStyle'|'Stretch'|'PreviewOnly'|'ReadOnly'
export type StyleNameA=StyleName|'AlignJustify'

//单位
export type Unit='px'|'mm'|'cm'|'pt'|'%'
export const UnitArr:Array<Unit> = ['px', 'mm', 'cm', 'pt', '%']

//字体
export type FontName='Microsoft YaHei'|'宋体'
export const FontList:Array<FontName> = ['Microsoft YaHei', '宋体']
//默认单位
export const baseUnit:Unit = 'px'

//页面尺寸 px
export interface PageSize{
  width:number|string
  height:number|string
}


export const DefaultPageSize = 'A5'
/**
 * Lodop 中的px单位固定换算关系如下,与像素类似但不是一个概念，也不受显示影响：
   1in(英寸)=2.54cm(厘米)=25.4mm(毫米)=72pt(磅)=96px
   A4 210mm×297mm  A5 148mm×210mm
 */
export const PageSizeHash:Dictionary<PageSize> = {
  'A4':{width:794, height:1123},
  'A5':{width:559, height:794},
  '5cm*3cm':{width:189, height:113},
  '5cm*4cm':{width:189, height:151},
  '8cm*5cm':{width:302, height:189}
}

export const PageSizeCHashMM:Dictionary<PageSize> = {
  'A4':{width:'210mm', height:'297mm'},
  'A5':{width:'148mm', height:'210mm'},
  '5cm*3cm':{width:'50mm', height:'30mm'},
  '5cm*4cm':{width:'50mm', height:'40mm'},
  '8cm*5cm':{width:'80mm', height:'50mm'}
}


//获取图片元素的html
export const getImageHtmlStr = (src:string, width?:number, height?:number) => {
  //设置足够大的宽高 让下载引擎传给Lodop图片质量足够好
  return `<img src=${src} transcolor="#FFFFFF"  width=${width ? width : 2000} height=${height ? height : 2000}" />`
}

//打印开始前的设置
export const beforPrintset = (type:PrintType, _taskName?:string):Clodop|null => {
  const status:CLodopStatus = cLodopStore.getLodopStatus
  const clodop = getCLodop()
  if (status === CLodopStatus.Ready && clodop) {
    resetLicenses(clodop)
    const taskName = _taskName ? _taskName : Date.now() + ''
    const inited = clodop.PRINT_INIT(taskName)
    //初始化失败
    if (!inited) {
      ElMessage.error('打印控件初始化失败')
      return null
    }
    //指定打印机不存在
    const printName = getPrintName(type)
    const print = clodop.SET_PRINTER_INDEX(printName)
    if (!print) return null
    return clodop
  } else {
    return null
  }
}

//打印图片
export const printImage = (type:PrintType, mode:PrintMode, base64Data:string, width:number, height:number):boolean => {
  const clodop = beforPrintset(type)
  if (clodop) {
    //纸张边缘为基点
    clodop.SET_PRINT_MODE('POS_BASEON_PAPER', true)
    //设置纸张大小
    clodop.SET_PRINT_PAGESIZE(0, width + 'mm', height + 'mm', '')
    clodop.ADD_PRINT_IMAGE(0, 0, width + 'mm', height + 'mm', base64Data)
    if (mode === 'print') {
      clodop.PRINT()
    }
    else if (mode === 'preview') {
      clodop.PREVIEW()
    }
    return true
  } else {
    return false
  }
}

//打印pdf
export const printPdf = (type:PrintType, mode:PrintMode, base64Data:string, duplex?:boolean):boolean => {
  const clodop = beforPrintset(type)
  if (clodop) {
    //纸张边缘为基点
    clodop.SET_PRINT_MODE('POS_BASEON_PAPER', true)
    //设置双面打印
    if (duplex) {
      //0-不控制 1-不双面 2-双面(长边装订) 3-小册子双面(短边装订_长边水平)
      clodop.SET_PRINT_MODE('PRINT_DUPLEX', 2)
      //1-纸盒 4-手动 7-自动 0-不控制
      clodop.SET_PRINT_MODE('PRINT_DEFAULTSOURCE', 1)
    }
    clodop.ADD_PRINT_PDF(0, 0, '100%', '100%', base64Data)
    clodop.SET_PRINT_STYLEA(0, 'PDFScalMode', 1)
    clodop.SET_PRINT_PAGESIZE(3, 0, 0, '')
    if (mode === 'print') {
      clodop.PRINT()
    }
    else if (mode === 'preview') {
      clodop.PREVIEW()
    }
    return true
  } else {
    return false
  }
}